import sys
import MainForm
from PyQt5 import QtCore, QtWidgets
from PyQt5.QtWidgets import *
from PyQt5.QtCore import QTimer
from functools import partial
import signal
import DialogAgreement
import DialogResult
import subprocess
import os
import logging
from Common import MakeSDUIThread, MSInstallUIThread, ConnectThread
from make_sd import MakeSDCard
from install_MindStudio import MindStudioInstall
from PasswdManager import PasswdManager
from Common import ADKUtils
import configparser
import paramiko
import time
import encodings.idna
import psutil


class ADKInstaller:

    def __init__(self, language):

        # self.project_path = os.path.split(os.path.realpath(__file__))[0]
        self.project_path = os.path.dirname(os.path.abspath(sys.argv[0]))
        self.download_path = os.path.join(self.project_path, "log")
        self.logfile = os.path.join(self.project_path, "ADKInstaller.log")

        self.ui = MainForm.Ui_MainForm()
        self.passwd = passmanager.read_decode_func(self.project_path)
        self.language = language

        # log for make SD card.
        self.logger = logging.getLogger()
        self.logger.setLevel(logging.DEBUG)

        try:
            fh = logging.FileHandler(filename=self.logfile)
            fmt = logging.Formatter('%(asctime)s - %(levelname)s - %(threadName)s - %(message)s')
            fh.setFormatter(fmt)
            self.logger.addHandler(fh)

            # todo: print to screen
            sh = logging.StreamHandler()
            sh.setFormatter(fmt)
            self.logger.addFilter(sh)

        except IOError:
            print("ERROR, logger initial failed, please check, logfile=" + self.logfile)
            exit(0)
        else:
            print("log file:" + self.logfile)

    def do_make_sd_end(self):
        self.ui.pushButton_makesd.setEnabled(True)

    def show_message(self, msg):
        dialog_result = QDialog()
        result_ui = DialogResult.Ui_Dialog()
        result_ui.setupUi(dialog_result)
        result_ui.label.setText(msg)

        if dialog_result.exec() == QDialog.Accepted:
            print(msg)
            return

    def get_virtual_net_card(self):
        self.ui.step2_connect200dk.comboBox_virtual_net_card.clear()

        usb_ethnet_cards_from_dmesg = subprocess.getstatusoutput('dmesg | grep "renamed from usb" | sort -r | cut -d ":" -f 2| cut -c 5- | uniq')[1].split('\n')

        self.logger.info("usb_ethnet_cards_from_dmesg: ")
        self.logger.info(usb_ethnet_cards_from_dmesg)

        (ret, ifconfig_output) = subprocess.getstatusoutput('ifconfig')

        self.logger.info("get ifconfig result:\n" + ifconfig_output)

        while ret != 0:

            if self.passwd is None or self.passwd == "":
                continue
            (ret, ifconfig_output) = subprocess.getstatusoutput('echo ' + self.passwd + ' | sudo -S ifconfig')

        valid_usb_cards = []

        for usb_card in usb_ethnet_cards_from_dmesg:

            if ifconfig_output.find(usb_card) >= 0:
                if usb_card == '':
                    continue
                valid_usb_cards.append(usb_card)

        if len(valid_usb_cards) < 1:
            if self.language == "English":
                self.show_message('No any usb ethernet found! \n 1. Do you connect the Atlas 200 DK developer board to your PC over USB port? \n  2. If you use VM(VMware or VirtualBox), please be sure the Atlas 200 DK developer board connected to the VM. ')
            else:
                self.show_message("没有找到USB网卡！\n 1.你是否已经使用了USB线连接了Atlas 200 DK和Ubuntu服务器？\n 2.如果你使用的是虚拟机，请确保Atlas 200 DK连接到了虚拟机内。")
        self.ui.step2_connect200dk.comboBox_virtual_net_card.addItems(valid_usb_cards)

    def already_connect(self, isconnected, ip):
        if isconnected:
            self.ui.step2_connect200dk.pushButton_connect_next.setEnabled(True)
            self.ui.step2_connect200dk.pushButton_connect.setEnabled(True)
            self.show_message("%s is connected, no need config again." % ip)
            ADKUtils.disable_item_comboBox(self.ui.step2_connect200dk.comboBox_default_ip, [0, 1], 1 | 32)
            self.ui.step2_connect200dk.pushButton_refresh.setEnabled(True)
            ADKUtils.disable_item_comboBox(self.ui.step2_connect200dk.comboBox_virtual_net_card, [0, 1], 1 | 32)

    def customize_show(self, flag, output):
        if flag:
            self.show_message(output + "\nif you want to configure again, please remove it from the file:\n/etc/network/interfaces. \nand check your remote ip")
            _translate = QtCore.QCoreApplication.translate
            self.ui.step2_connect200dk.comboBox_default_ip.setItemText(2, _translate("Dialog", "customize"))
            self.ui.step2_connect200dk.pushButton_connect.setEnabled(True)
            self.ui.step2_connect200dk.pushButton_connect.setEnabled(True)
            ADKUtils.disable_item_comboBox(self.ui.step2_connect200dk.comboBox_default_ip, [0, 1], 1 | 32)
            self.ui.step2_connect200dk.pushButton_refresh.setEnabled(True)
            ADKUtils.disable_item_comboBox(self.ui.step2_connect200dk.comboBox_virtual_net_card, [0, 1], 1 | 32)

    def config_result(self, result, card, ip, remote_ip):
        if result:
            self.show_message("Configuration success.\n"
                          " usb network card: %s, ip: %s\n"
                          "remote device ip: %s" % (card, ip, remote_ip))
            self.ui.step2_connect200dk.pushButton_connect_next.setEnabled(True)
            self.ui.step2_connect200dk.pushButton_connect.setEnabled(True)
            ADKUtils.disable_item_comboBox(self.ui.step2_connect200dk.comboBox_default_ip, [0, 1], 1 | 32)
            self.ui.step2_connect200dk.pushButton_refresh.setEnabled(True)
            ADKUtils.disable_item_comboBox(self.ui.step2_connect200dk.comboBox_virtual_net_card, [0, 1], 1 | 32)

    def do_connect(self):

        self.ui.step2_connect200dk.pushButton_connect.setEnabled(False)
        self.ui.step2_connect200dk.pushButton_connect_next.setText("Next")
        self.ui.step2_connect200dk.pushButton_connect_next.setEnabled(False)
        ADKUtils.disable_item_comboBox(self.ui.step2_connect200dk.comboBox_default_ip, [0, 1], 0)
        ADKUtils.disable_item_comboBox(self.ui.step2_connect200dk.comboBox_virtual_net_card, [0, 1], 0)
        self.ui.step2_connect200dk.pushButton_refresh.setEnabled(False)
        _translate = QtCore.QCoreApplication.translate
        self.usb_card = self.ui.step2_connect200dk.comboBox_virtual_net_card.currentText()
        self.remote_ip = self.ui.step2_connect200dk.comboBox_default_ip.currentText()
        if self.usb_card == "":
            self.show_message("please choose the virtual net card")
            self.ui.step2_connect200dk.pushButton_connect.setEnabled(True)
            self.ui.step2_connect200dk.pushButton_connect_next.setText("Skip")
            self.ui.step2_connect200dk.pushButton_connect_next.setEnabled(True)
            ADKUtils.disable_item_comboBox(self.ui.step2_connect200dk.comboBox_default_ip, [0, 1], 1 | 32)
            self.ui.step2_connect200dk.pushButton_refresh.setEnabled(True)
            ADKUtils.disable_item_comboBox(self.ui.step2_connect200dk.comboBox_virtual_net_card, [0, 1], 1 | 32)
            return
        self.connect_thread = ConnectThread(remote_ip=self.remote_ip, usb_card=self.usb_card, passwd=self.passwd, project_path=self.project_path)
        self.connect_thread.already_connect_signal.connect(self.already_connect)
        self.connect_thread.customize_signal.connect(self.customize_show)
        self.connect_thread.configure_signal.connect(self.config_result)
        self.connect_thread.start()


class myMainWindow(QMainWindow):
    def __init__(self):
        super().__init__()

    def closeEvent(self, event):
        ret, output = subprocess.getstatusoutput('ps -ef |grep apt')
        if output.find('apt-get install') == -1 and output.find('apt-get update') == -1:
            event.accept()
            return
        quitMsgBox = QMessageBox()
        quitMsgBox.setWindowTitle('message')
        quitMsgBox.setText('Apt in running, if you exit, the apt thread will break.')
        quitMsgBox.setStandardButtons(QMessageBox.Yes | QMessageBox.No)
        buttonY = quitMsgBox.button(QMessageBox.Yes)
        buttonN = quitMsgBox.button(QMessageBox.No)
        quitMsgBox.exec_()
        if quitMsgBox.clickedButton() == buttonY:
            event.accept()
        else:
            event.ignore()


def sigint_handler(*args):
    sys.stderr.write('\r')
    QApplication.quit()


def write_pid():
    pid = os.getpid()
    fp = open("pid.log", 'w')
    fp.write(str(pid))
    fp.close()


def read_pid():
    if os.path.exists("pid.log"):
        fp = open("pid.log", 'r')
        pid = fp.read()
        fp.close()
        return pid
    else:
        return '0'


if __name__ == '__main__':
    signal.signal(signal.SIGINT, sigint_handler)
    app = QApplication(sys.argv)
    timer = QTimer()
    timer.start(500)
    timer.timeout.connect(lambda: None)

    MainWindow = myMainWindow()

    project_path = os.path.dirname(os.path.abspath(sys.argv[0]))

    passmanager = PasswdManager()

    passmanager.get_passwd()

    language = passmanager.get_passwd_ui.comboBox.currentText()

    conf = configparser.ConfigParser()
    conf.read(project_path + "/config.ini")
    conf.set("Language_info", "language", language)
    conf.write(open(project_path + "/config.ini", "w", encoding="utf-8"))

    pid = int(read_pid())
    if pid:
        running_pid = psutil.pids()
        if pid in running_pid:
            print("ADKInstaller is running.")
            sys.exit()
        else:
            write_pid()
    else:
        write_pid()

    adk_manager = ADKInstaller(language=language)

    adk_manager.ui.setupUi(MainWindow, language=language)

    make_sd_god = MakeSDCard(adk_manager.ui.step1_make_sd_card, language)

    dialog_agreement = QDialog()
    agreement_ui = DialogAgreement.Ui_Dialog()
    agreement_ui.setupUi(dialog_agreement)
    make_sd_god.read_log_to_gui(make_sd_god.logfile)

    adk_manager.ui.step1_make_sd_card.pushButton.clicked.connect(make_sd_god.makesd_prepare)
    adk_manager.ui.step1_make_sd_card.checkBox_aggrement.clicked.connect(partial(make_sd_god.read_agreement, dialog_agreement))
    adk_manager.ui.step1_make_sd_card.pushButton_pause.clicked.connect(make_sd_god.prepare_pause)
    adk_manager.ui.step1_make_sd_card.flashButton.clicked.connect(lambda: adk_manager.ui.change(adk_manager.ui.pushButton_connect.objectName()))

    install_ms = MindStudioInstall(adk_manager.ui.step3_mindstudio)
    dialog_agreement = QDialog()
    agreement_ui = DialogAgreement.Ui_Dialog()
    agreement_ui.setupUi(dialog_agreement)

    install_ms.ui.pushButton.setEnabled(False)

    adk_manager.ui.step3_mindstudio.checkBox_aggrement.clicked.connect(partial(install_ms.read_agreement, dialog_agreement))
    adk_manager.ui.step3_mindstudio.pushButton.clicked.connect(install_ms.install_ms_prepare)
    adk_manager.ui.step3_mindstudio.pushButton_pause.clicked.connect(install_ms.prepare_pause)

    adk_manager.ui.step2_connect200dk.pushButton_connect.clicked.connect(adk_manager.do_connect)
    adk_manager.ui.step2_connect200dk.pushButton_refresh.clicked.connect(adk_manager.get_virtual_net_card)
    adk_manager.ui.step2_connect200dk.pushButton_connect_next.clicked.connect(lambda: adk_manager.ui.change(adk_manager.ui.pushButton_ms_studio.objectName()))

    install_ms.read_log_to_gui(install_ms.logfile)

    MainWindow.show()

    sys.exit(app.exec_())
